package utils

// jwt.go
// 实现 JWT 相关功能

import (
	"errors"
	"gforum/config"
	"strings"
	"time"

	"github.com/golang-jwt/jwt/v5"
)

// GenerateJWT 生成一个带有用户名和过期时间的 token
func GenerateJWT(username string) (string, error) {
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
		"username": username,
		"exp":      time.Now().Add(config.Instance.JWT.Expires).Unix(),
	})

	signedToken, err := token.SignedString([]byte(config.Instance.JWT.Secret))
	return "Bearer " + signedToken, err
}

// ParseJWT 解析 token 中的 username 并返回
func ParseJWT(tokenStr string) (string, error) {
	tokenStr = extractToken(tokenStr)

	token, err := jwt.Parse(tokenStr,
		func(token *jwt.Token) (any, error) {
			if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
				return nil, errors.New("unexpect siging method")
			}
			return []byte(config.Instance.JWT.Secret), nil
		},
	)

	if err != nil {
		return "", err
	}

	if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
		username, ok := claims["username"].(string)
		if !ok {
			return "", errors.New("username claim is not string")
		}
		return username, nil
	}

	return "", errors.New("token failed parse")
}

func extractToken(tokenStr string) string {
	const prefix = "bearer "
	if len(tokenStr) >= len(prefix) && strings.EqualFold(tokenStr[:len(prefix)], prefix) {
		return strings.TrimSpace(tokenStr[len(prefix):])
	}
	return tokenStr
}
